package com.example.graphmovieapp.service.impl;

import com.example.graphmovieapp.domain.entity.Person;
import com.example.graphmovieapp.domain.entity.Movie;
import com.example.graphmovieapp.dto.MovieDTO;
import com.example.graphmovieapp.repository.PersonRepository;
import com.example.graphmovieapp.repository.MovieRepository;
import com.example.graphmovieapp.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * PersonService实现类，提供人物相关的业务操作
 * 
 * @author GraphMovieApp
 * @version 1.0
 */
@Service
@Transactional
public class PersonServiceImpl implements PersonService {

    private final PersonRepository personRepository;
    private final MovieRepository movieRepository;

    /**
     * 构造函数，注入Repository依赖
     * 
     * @param personRepository 人物Repository
     * @param movieRepository 电影Repository
     */
    @Autowired
    public PersonServiceImpl(PersonRepository personRepository, MovieRepository movieRepository) {
        this.personRepository = personRepository;
        this.movieRepository = movieRepository;
    }

    /**
     * 保存人物
     * 
     * @param person 要保存的人物
     * @return 保存后的人物
     */
    @Override
    @Transactional
    public Person savePerson(Person person) {
        if (person == null) {
            throw new IllegalArgumentException("人物不能为空");
        }
        return personRepository.save(person);
    }

    /**
     * 根据ID查找人物
     * 
     * @param id 人物ID
     * @return 匹配的人物，如果不存在则返回Optional.empty()
     */
    @Override
    @Transactional(readOnly = true)
    public Optional<Person> findPersonById(Long id) {
        if (id == null) {
            throw new IllegalArgumentException("人物ID不能为空");
        }
        return personRepository.findById(id);
    }

    /**
     * 查找所有人物
     * 
     * @return 所有人物列表
     */
    @Override
    @Transactional(readOnly = true)
    public List<Person> findAllPersons() {
        return personRepository.findAll();
    }

    /**
     * 根据ID删除人物
     * 
     * @param id 人物ID
     */
    @Override
    @Transactional
    public void deletePerson(Long id) {
        if (id == null) {
            throw new IllegalArgumentException("人物ID不能为空");
        }
        if (!personRepository.existsById(id)) {
            throw new IllegalArgumentException("人物不存在，ID: " + id);
        }
        personRepository.deleteById(id);
    }

    /**
     * 根据姓名查找人物
     * 
     * @param name 人物姓名
     * @return 匹配的人物，如果不存在则返回Optional.empty()
     */
    @Override
    @Transactional(readOnly = true)
    public Optional<Person> findPersonByName(String name) {
        if (name == null || name.trim().isEmpty()) {
            throw new IllegalArgumentException("人物姓名不能为空");
        }
        return personRepository.findByName(name);
    }

    /**
     * 根据出生年份查找人物
     * 
     * @param born 出生年份
     * @return 匹配的人物列表
     */
    @Override
    @Transactional(readOnly = true)
    public List<Person> findPersonsByBorn(Integer born) {
        if (born == null) {
            throw new IllegalArgumentException("出生年份不能为空");
        }
        return personRepository.findByBorn(born);
    }

    /**
     * 根据姓名模糊查询人物
     * 
     * @param name 姓名关键字
     * @return 包含关键字的人物列表
     */
    @Override
    @Transactional(readOnly = true)
    public List<Person> findPersonsByNameContaining(String name) {
        if (name == null || name.trim().isEmpty()) {
            throw new IllegalArgumentException("姓名关键字不能为空");
        }
        return personRepository.findByNameContaining(name);
    }

    /**
     * 根据姓名模糊查询人物（支持分页）
     * 
     * @param name 姓名关键字
     * @param pageable 分页参数
     * @return 分页的人物列表
     */
    @Override
    @Transactional(readOnly = true)
    public Page<Person> findPersonsByNameContaining(String name, Pageable pageable) {
        if (name == null || name.trim().isEmpty()) {
            throw new IllegalArgumentException("姓名关键字不能为空");
        }
        if (pageable == null) {
            throw new IllegalArgumentException("分页参数不能为空");
        }
        return personRepository.findByNameContaining(name, pageable);
    }

    /**
     * 查找指定演员参演的所有电影
     * 
     * @param name 演员姓名
     * @return 该演员参演的电影列表
     */
    @Override
    @Transactional(readOnly = true)
    public List<Movie> findMoviesActedByPerson(String name) {
        if (name == null || name.trim().isEmpty()) {
            throw new IllegalArgumentException("演员姓名不能为空");
        }
        return personRepository.findMoviesActedByPerson(name);
    }

    /**
     * 查找指定导演执导的所有电影
     * 
     * @param name 导演姓名
     * @return 该导演执导的电影列表
     */
    @Override
    @Transactional(readOnly = true)
    public List<Movie> findMoviesDirectedByPerson(String name) {
        if (name == null || name.trim().isEmpty()) {
            throw new IllegalArgumentException("导演姓名不能为空");
        }
        return personRepository.findMoviesDirectedByPerson(name);
    }

    /**
     * 查找参演指定电影的演员
     * 
     * @param title 电影标题
     * @return 参演该电影的演员列表
     */
    @Override
    @Transactional(readOnly = true)
    public List<Person> findActorsInMovie(String title) {
        if (title == null || title.trim().isEmpty()) {
            throw new IllegalArgumentException("电影标题不能为空");
        }
        return personRepository.findActorsInMovie(title);
    }

    /**
     * 查找指定电影的导演
     * 
     * @param title 电影标题
     * @return 该电影的导演列表
     */
    @Override
    @Transactional(readOnly = true)
    public List<Person> findDirectorsOfMovie(String title) {
        if (title == null || title.trim().isEmpty()) {
            throw new IllegalArgumentException("电影标题不能为空");
        }
        return personRepository.findDirectorsOfMovie(title);
    }

    /**
     * 添加演员到电影
     * 
     * @param personName 演员姓名
     * @param movieTitle 电影标题
     * @return 更新后的人物
     */
    @Override
    @Transactional
    public Person addActorToMovie(String personName, String movieTitle) {
        if (personName == null || personName.trim().isEmpty()) {
            throw new IllegalArgumentException("演员姓名不能为空");
        }
        if (movieTitle == null || movieTitle.trim().isEmpty()) {
            throw new IllegalArgumentException("电影标题不能为空");
        }

        // 查找人物
        Optional<Person> personOpt = personRepository.findByName(personName);
        if (!personOpt.isPresent()) {
            throw new IllegalArgumentException("演员不存在: " + personName);
        }
        Person person = personOpt.get();

        // 查找电影
        Optional<Movie> movieOpt = movieRepository.findByTitle(movieTitle);
        if (!movieOpt.isPresent()) {
            throw new IllegalArgumentException("电影不存在: " + movieTitle);
        }
        Movie movie = movieOpt.get();

        // 建立关系
        person.addActedInMovie(movie);
        movie.addActor(person);

        // 保存更新
        return personRepository.save(person);
    }

    /**
     * 添加导演到电影
     * 
     * @param personName 导演姓名
     * @param movieTitle 电影标题
     * @return 更新后的人物
     */
    @Override
    @Transactional
    public Person addDirectorToMovie(String personName, String movieTitle) {
        if (personName == null || personName.trim().isEmpty()) {
            throw new IllegalArgumentException("导演姓名不能为空");
        }
        if (movieTitle == null || movieTitle.trim().isEmpty()) {
            throw new IllegalArgumentException("电影标题不能为空");
        }

        // 查找人物
        Optional<Person> personOpt = personRepository.findByName(personName);
        if (!personOpt.isPresent()) {
            throw new IllegalArgumentException("导演不存在: " + personName);
        }
        Person person = personOpt.get();

        // 查找电影
        Optional<Movie> movieOpt = movieRepository.findByTitle(movieTitle);
        if (!movieOpt.isPresent()) {
            throw new IllegalArgumentException("电影不存在: " + movieTitle);
        }
        Movie movie = movieOpt.get();

        // 建立关系
        person.addDirectedMovie(movie);
        movie.addDirector(person);

        // 保存更新
        return personRepository.save(person);
    }
}